﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OthelloCognition;
using OthelloGame;
using System.Threading;

namespace OthelloConsole
{
    class OthelloConsoleGame
    {
        #region PrivateMembers
        private AbstractSolver blackPlayer, whitePlayer;

        private OthelloGameBoard board;
        
        private int[,] moveHistory = new int[60,3];
        public int[,] MoveHistory {
            get { return moveHistory; }
        }

        private int[] gameResults = new int[2];
        public int[] GameResults {
            get { return gameResults; }
        }

        private int currentMoveNumber = 0, 
                    turnTime = 0;
        
        #endregion

        public OthelloConsoleGame(AbstractSolver wp, AbstractSolver bp, int turnTimeInMS)
        {
            whitePlayer = wp;
            blackPlayer = bp;
            turnTime = turnTimeInMS;

            board = new OthelloGameBoard();
        }

        public void playGame()
        {
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
            Console.WriteLine("Starting game");
            while(!board.GameOver()) 
            {
                Thread playerThread = new Thread(new ThreadStart(takeTurn));
                playerThread.Priority = ThreadPriority.AboveNormal;
                playerThread.Name = Convert.ToString(currentMoveNumber);
                playerThread.Start();

                Thread.CurrentThread.Join(turnTime);
                try
                {
                    playerThread.Abort();
                }
                catch
                {
                    // Don't really care, just stopped the player's turn.
                }

                OthelloBoardLocation move = currentPlayer.nextMove;
                if (board.AvailableOptionLocations.Contains(move))
                {
                    addMove(move, currentPlayer.expanded, turnTime);
                    board.PlacePit(move);
                }
                else
                {
                    Console.WriteLine("Player attempted invalid move, quitting");
                    Console.Read();
                    Environment.Exit(1);
                }
            }

            gameResults[0] = board.BlackCount;
            gameResults[1] = board.WhiteCount;

            if (gameResults[0] < gameResults[1]) {
                whitePlayer.recordResult(true);
                blackPlayer.recordResult(false);
            }
            else if (gameResults[0] > gameResults[1])
            {
                whitePlayer.recordResult(false);
                blackPlayer.recordResult(true);
            }
            else
            {
                whitePlayer.recordResult(false);
                blackPlayer.recordResult(false);
            }
        }

        private void takeTurn()
        {
            currentPlayer.searchGameState(board);
        }

        private void addMove(OthelloBoardLocation obl, int states, int time)
        {
            int sign = 1;
            if (currentPlayer != blackPlayer)
            {
                sign = -1;
            }
            
            moveHistory[currentMoveNumber,0] = sign * (obl.HorizontalPlace * 10 + obl.VerticalPlace);
            moveHistory[currentMoveNumber,1] = states;
            moveHistory[currentMoveNumber,2] = time;
            currentMoveNumber++;
        }

        private AbstractSolver currentPlayer
        {
            get
            {
                if (board.PlayersTurn == OthelloGame.PieceColors.Black)
                {
                    return blackPlayer;
                }
                else
                {
                    return whitePlayer;
                }
            }
        }
    }
}
